<?php

namespace app\api\index\v1\service;

use app\constant\ApiCode;
use app\provider\SmsProvider;
use app\provider\User;
use zhanshop\App;

class PassportService
{
    /**
     * 手机号码登录
     * @param array $appData
     * @param array $data
     * @return array
     * @throws \RedisException
     */
    public function phoneLogin(array $appData, array $data)
    {
        $area = strval($data['area'] ?? "");
        $phone = strval($data['phone'] ?? "");
        $code = strval($data['code'] ?? "");
        if($area == "+86"){
            $rule = '/^1[3-9]\d{9}$/';
            $bool = is_scalar($phone) && 1 === preg_match($rule, (string) $phone);
            if($bool == false){
                App::error()->setError("手机号码输入错误", ApiCode::BAD_REQUEST);
            }
            if(App::make(SmsProvider::class)->getCode($appData['app'], $area, $phone) != $code){
                App::error()->setError("短信验证码错误", ApiCode::BAD_REQUEST);
            }
        }
        $sns = App::database()->model("user_sns")->where(['app' => $appData['app'], 'open_id' => $area.$phone])->find();
        $phone = $area.$phone;
        $userId = $sns['user_id'] ?? 0;
        $isRegister = false;
        if($sns == false){
            App::database()->transaction(function($pdo) use ($appData, $phone, &$userId, &$isRegister){
                $time = time();
                $userId = App::database()->model("user_account")->insertGetId([
                    'app' => $appData['app'],
                    'user_name' => $phone,
                    'regip' => $appData['ip'],
                    'create_time' => $time,
                ], $pdo);
                App::database()->model("user_sns")->insertGetId([
                    'app' => $appData['app'],
                    'user_id' => $userId,
                    'open_id' => $phone,
                    'sns_type' => 'phone',
                    'create_time' => $time,
                    'update_time' => $time,
                ], $pdo);
                App::database()->model('user_info')->insert([
                    'app' => $appData['app'],
                    'user_id' => $userId,
                    'channel' => $appData['channel'] ?? "",
                    'regip' => $appData['ip'],
                    'phone' => $phone,
                    'create_time' => $time,
                    'update_time' => $time,
                ], $pdo);
                $isRegister = true;
            });
        }else{
            App::database()->model("user_info")->where(['app' => $appData['app'], 'user_id' => $userId])->update(['cancel_time' => 0]);
        }
        return [
            'status' => 'finish',
            'user_id' => $userId,
            'is_register' => $isRegister,
            'token' => App::aes()->encrypt($userId.','.time())
        ];
    }

    /**
     * 微信登录
     * @param array $appData
     * @param array $data
     * @return void
     */
    public function wechat(array $appData, array $data, bool $bindPhone = true)
    {
        $unionid = $data['unionid'];
        $result = [
            'status' => 'finish',
            'user_id' => 0,
            'is_register' => false,
            'token' => ''
        ];
        if($unionid){
            $result['user_id'] = App::database()->model("user_sns")->where(['app' => $appData['app'], 'sns_type' => 'wechat', 'unionid' => $unionid])->value('user_id');
        }

        if($result['user_id'] == false){
            $openid = $data['openid'] ?? App::error()->setError("微信openid获取失败", ApiCode::EXPECTATION_FAILED);
            $result['user_id'] = App::database()->model("user_sns")->where(['app' => $appData['app'], 'sns_type' => 'wechat', 'open_id' => $openid])->value('user_id');
        }

        if($result['user_id'] == false){
            if($bindPhone){
                $result['status'] = 'bind';
                $data['sns_type'] = 'wechat';
                $result['token'] = App::aes()->encrypt(json_encode($data));
            }else{
                App::database()->transaction(function($pdo) use ($appData, $data, &$result){
                    $openid = $data['unionid'] ?? '';
                    if($openid == false) $openid = $data['openid'];
                    $time = time();
                    $userId = App::database()->model("user_account")->insertGetId([
                        'app' => $appData['app'],
                        'user_name' => $openid,
                        'regip' => $appData['ip'],
                        'create_time' => $time,
                    ], $pdo);
                    App::database()->model("user_sns")->insertGetId([
                        'app' => $appData['app'],
                        'user_id' => $userId,
                        'open_id' => $openid,
                        'sns_type' => 'wechat',
                        'create_time' => $time,
                        'update_time' => $time,
                    ], $pdo);
                    App::database()->model('user_info')->insert([
                        'app' => $appData['app'],
                        'user_id' => $userId,
                        'channel' => $appData['channel'] ?? "",
                        'regip' => $appData['ip'],
                        'phone' => '',
                        'create_time' => $time,
                        'update_time' => $time,
                    ], $pdo);
                    $result['user_id'] = $userId;
                    $result['is_register'] = true;
                });
            }
        }else{
            App::database()->model("user_info")->where(['app' => $appData['app'], 'user_id' => $result['user_id']])->update(['cancel_time' => 0]);
        }
        if($result['user_id']){
            $result['token'] = App::aes()->encrypt($result['user_id'].','.time());
        }
        return $result;
    }

    /**
     * 友盟一键登录
     * @param array $data
     * @return void
     */
    public function umeng(array $appData, array $data)
    {
        $token = $data['token'] ?? App::error()->setError("友盟openid获取失败", ApiCode::EXPECTATION_FAILED);
        App::error()->setError('暂不支持友盟登录方式', 404);
        //$codes['phone'] = App::rpc(PhoneAuth::class, $app, $device['ip'] ?? time())->mobileInfo($token);
        //return $this->phone($app, $codes, $device, false);
    }

    /**
     * 注册绑定
     * @param array $appData
     * @param string|null $token
     * @param array $data
     * @return array
     * @throws \Exception
     */
    public function regBind(array $appData, ?string $token, array $data)
    {
        $openid = '';
        $opentype = '';
        try {
            $token = App::aes()->decrypt($token);
            $token = json_decode($token, true);
            $openid = $token['unionid'] ?? '';
            if($openid == false) $openid = $token['openid'];
            $opentype = $token['sns_type'];
        }catch (\Throwable $exception){
            App::error()->setError("无效TOKEN", ApiCode::EXPECTATION_FAILED);
        }

        $result = $this->phoneLogin($appData, $data);

        $time = time();
        App::database()->model("user_sns")->insertGetId([
            'app' => $appData['app'],
            'user_id' => $result['user_id'],
            'open_id' => $openid,
            'sns_type' => $opentype,
            'create_time' => $time,
            'update_time' => $time,
        ]);

        return $result;
    }

    public function __call(string $name, array $arguments)
    {
        App::error()->setError('暂不支持'.$name.'登录方式', 404);
    }
}